<?php
/**
 * Created by PhpStorm.
 * User: nightelf
 * Date: 2020/12/13
 * Time: 22:16
 */

namespace App\Http\Model;


use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class WarehouseAdjustModel
{
    const CHECK = 1;
    const COMPLETE = 2;
    const SUCCESS = 3;
    const CANCEL = 4;

    public function adjust(Array $data)
    {
        DB::beginTransaction();
        try {
            //写入调拨记录
            $adjustData = [
                'outProjectId' => $data['projectId'],
                'inProjectId' => $data['newProjectId'],
                'time' => $data['time'],
                'createTime' => date('Y-m-d H:i:s'),
                'remark' => $data['remark'],
                'adminId' => $data['adminId'],
            ];
            $adjustId = DB::table('warehouse_adjust')->insertGetId($adjustData);

            //遍历调拨材料
            foreach ($data['data'] as $d) {
                $material = DB::table('warehouse')
                    ->where(['materialId' => $d['materialId'], 'specId' => $d['specId'], 'projectId' => $data['projectId']])
                    ->first();
                $adjustInfo = [
                    'adjustId' => $adjustId,
                    'materialId' => $d['materialId'],
                    'specId' => $d['specId'],
                    'amount' => $d['amount'],
                    'price' => $material->purchasePrice,
                    'totalPrice' => $material->purchasePrice * $d['amount'],
                    'unitId' => $d['unitId'],
                ];
                //记录调拨材料明细
                DB::table('warehouse_adjust_info')->insert($adjustInfo);

                //扣减材料库存
                $newAmount = $material->amount - $d['amount'];
                DB::table('warehouse')
                    ->where(['materialId' => $d['materialId'], 'specId' => $d['specId'], 'projectId' => $data['projectId']])
                    ->update(['amount' => $newAmount]);
            }
            DB::commit();
            return true;
        } catch (\Exception $e) {
            Log::info($e->getMessage() . ' in ' . $e->getFile() . '(' . $e->getLine() . ')');
            DB::rollback();
            return false;
        }
    }

    /**
     * @param array $data
     * @return mixed
     */
    public function lists(array $data)
    {
        $result = DB::table('warehouse_adjust')
            ->leftJoin('project as p', 'p.id', '=', 'warehouse_adjust.outProjectId')
            ->leftJoin('project as pp', 'pp.id', '=', 'warehouse_adjust.inProjectId')
            ->leftJoin('admin as a', 'a.id', '=', 'warehouse_adjust.adminId')
            ->where(function ($query) use ($data) {
                if (!empty($data['startTime'])) {
                    $query->where('warehouse_adjust.time', '>', $data['startTime']);
                }
                if (!empty($data['endTime'])) {
                    $query->where('warehouse_adjust.time', '<', $data['endTime']);
                }
                if ($data['status'] != null ||$data['status'] != '') {
                    $query->where('warehouse_adjust.status', $data['status']);
                }
            })
            ->where(function ($query) use ($data) {
                $query->where('outProjectId', $data['projectId'])->orWhere('inProjectId', $data['projectId']);
            });
        if (!empty($data['length']) && !empty($data['page'])) {
            $limit = config('yucheng.limit');
            $start = 0;
            if (!empty($data['length'])) {
                $limit = $data['length'];
            }
            if (!empty($data['page'])) {
                $start = ($data['page'] - 1) * $limit;
            }
            $result = $result->offset($start)->limit($limit);
        }
        return $result->select('warehouse_adjust.*', 'p.name as outProjectName', 'pp.name as inProjectName','a.name as adminName')->orderBy('time','desc')
            ->get()->toArray();
    }

    /**
     * @param array $data
     * @return mixed
     */
    public function countLists(array $data)
    {
        return DB::table('warehouse_adjust')
            ->leftJoin('project as p', 'p.id', '=', 'warehouse_adjust.outProjectId')
            ->leftJoin('project as pp', 'p.id', '=', 'warehouse_adjust.inProjectId')
            ->leftJoin('admin as a', 'a.id', '=', 'warehouse_adjust.adminId')
            ->where(function ($query) use ($data) {
                if (!empty($data['startTime'])) {
                    $query->where('warehouse_adjust.time', '>', $data['startTime']);
                }
                if (!empty($data['endTime'])) {
                    $query->where('warehouse_adjust.time', '<', $data['endTime']);
                }
                if ($data['status'] != null ||$data['status'] != '') {
                    $query->where('warehouse_adjust.status', $data['status']);
                }
            })
            ->where(function ($query) use ($data) {
                $query->where('outProjectId', $data['projectId'])->orWhere('inProjectId', $data['projectId']);
            })
            ->count();
    }

    public function delete(array $param)
    {

        DB::beginTransaction();
        try {
            $adjust = DB::table('warehouse_adjust')->where($param)->first();
            $adjustInfo = DB::table('warehouse_adjust_info')->where(['adjustId' => $param['id']])->get()->toArray();
            foreach ($adjustInfo as $a){
                DB::table('warehouse')
                    ->where([
                        'projectId'=>$adjust->outProjectId,
                        'materialId'=>$a->materialId,
                        'specId'=>$a->specId,
                    ])
                    ->increment('amount',$a->amount);
            }
            DB::table('warehouse_adjust')->where($param)->delete();
            DB::table('warehouse_adjust_info')->where(['adjustId' => $param['id']])->delete();
            DB::commit();
            return true;
        } catch (\Exception $e) {
            Log::info('Error:' . $e->getMessage() . ' at ' . $e->getFile() . ' line:' . $e->getLine() . '\n' . $e->getTraceAsString());
            DB::rollback();
        }
    }

    public function receive(array $param)
    {
        DB::beginTransaction();
        try {
            //调拨收货记录
            $data1 = [
                'adjustId' => $param['adjustId'],
                'adminId' => $param['adminId'],
                'receivingTime' => $param['receivedTime'],
            ];
            $receivingId = DB::table('warehouse_adjust_receiving')->insert($data1);
            $data2 = [];
//            $allComplete = true;
            //构建出入库记录所需的数据
            foreach ($param['data'] as $d) {
                //调拨记录、调拨收货记录
                $info = DB::table('warehouse_adjust_info')->where(['id' => $d['id']])->first();
                $info = empty($info) ? [] : get_object_vars($info);
                //构建收货明细的数据
                $data2[] = [
                    'receivingId' => $receivingId,
                    'adjustId' => $param['adjustId'],
                    'adjustInfoId' => $d['id'],
                    'materialId' => $info['materialId'],
                    'specId' => $info['specId'],
                    'amount' => $d['received'],
                    'remark' => $d['remark'],
                ];
                $newQuantity = $info['receivedQuantity'] + $d['received'];
                if ($newQuantity >= $info['amount']) {
                    $status = 2;
                } else {
                    $status = 1;
                }
                //更新订单明细的收货数量和明细的收获状态
                DB::table('warehouse_adjust_info')->where(['id' => $d['id']])->update([
                    'receivedQuantity' => $newQuantity,
                    'status' => $status,
                ]);
                //判断整个订单是否已经完成
//                if ($status != self::COMPLETE) {
//                    $allComplete = false;
//                }
            }
            DB::table('warehouse_adjust_receiving_info')->insert($data2);
            DB::commit();
        } catch (\Exception $e) {
            Log::info('Error:' . $e->getMessage() . ' at ' . $e->getFile() . ' line:' . $e->getLine() . '\n' . $e->getTraceAsString());
            DB::rollback();
        }
    }

    public function complete(array $param)
    {
        DB::beginTransaction();
        try {
            //调拨单修改状态
            DB::table('warehouse_adjust')->where('id', $param['id'])->update(['status'=>3]);
        //出入库记录
            $adjust = DB::table('warehouse_adjust')->where('id', $param['id'])->first();
            $outLog = [
                'projectId'=>$adjust->outProjectId,
                'type'=>WarehouseLogModel::ALLOT,
                'sourceProjectId'=>$adjust->inProjectId,
                'time'=>$adjust->time,
                'createTime'=>$adjust->createTime,
                'remark'=>$adjust->remark,
                'adminId'=>$adjust->adminId,
            ];
            $inLog = [
                'projectId'=>$adjust->inProjectId,
                'type'=>WarehouseLogModel::RECEIPT,
                'sourceProjectId'=>$adjust->outProjectId,
                'time'=>$adjust->time,
                'createTime'=>$adjust->createTime,
                'remark'=>$adjust->remark,
                'adminId'=>$param['adminId'],
            ];
            $outLogId = DB::table('warehouse_log')->insertGetId($outLog);
            $inLogId = DB::table('warehouse_log')->insertGetId($inLog);
            $warehouseModel = new WarehouseModel();

            $adjustInfo = DB::table('warehouse_adjust_info')->where('adjustId', $param['id'])->get()->toArray();
            foreach ($adjustInfo as $a){
                $inLogData = $outLogData = [
                    'materialId' => $a->materialId,
                    'specId' => $a->specId,
                    'amount' => $a->receivedQuantity,
                    'unitId' => $a->unitId,
                    'price' => $a->price,
                    'totalPrice' => $a->totalPrice,
                ];
                $inLogData['logId'] = $inLogId;
                $outLogData['logId'] = $outLogId;
                DB::table('warehouse_log_info')->insert($outLogData);
                DB::table('warehouse_log_info')->insert($inLogData);

                //更新调出仓库的库存
                $warehouseOutData = [
                    'projectId' => $adjust->outProjectId,
                    'materialId' => $a->materialId,
                    'specId' => $a->specId,
                ];
                $materialOutInfo = $warehouseModel->info($warehouseOutData);
                $warehouseModel->update(['id' => $materialOutInfo['id']], ['amount'=>$materialOutInfo['amount']+$a->amount-$a->receivedQuantity]);
                //更新调入仓库的库存
                $warehouseInData = [
                    'projectId' => $adjust->inProjectId,
                    'materialId' => $a->materialId,
                    'specId' => $a->specId,
                ];
                $materialInfo = $warehouseModel->info($warehouseInData);
                if (empty($materialInfo)) {
                    //创建仓库新的材料库存
                    $warehouseInData = [
                        'projectId' => $adjust->inProjectId,
                        'materialId' => $a->materialId,
                        'specId' => $a->specId,
                        'amount' => $a->receivedQuantity,
                        'purchasePrice' => $a->price,
                        'salePrice' => 0,
                        'unitId' => $a->unitId,
                        'updateTime' => date('Y-m-d H:i:s'),
                    ];
                    (new WarehouseModel)->insert($warehouseInData);
                } else {
                    $newPrice = ($materialInfo['amount'] * $materialInfo['purchasePrice'] + $a->receivedQuantity * $a->price) / ($materialInfo['amount'] + $a->receivedQuantity);
                    //更新库存
                    $settingModel = new SettingModel();
                    $saleRate = $settingModel->get('saleRate', $adjust->inProjectId);
                    $salePrice = $newPrice * (1 + $saleRate);
                    $updateData = [
                        'amount' => $a->receivedQuantity + $materialInfo['amount'],
                        'purchasePrice' => $newPrice,
                        'salePrice' => $salePrice,
                        'updateTime' => date('Y-m-d H:i:s'),
                    ];
                    if (!$materialInfo['unitId']) {
                        $updateData['unitId'] = isset($a->unitId) ? intval($a->unitId) : 0;
                    }
                    //更新仓库库存数量及收储价格
                    $warehouseModel->update(['id' => $materialInfo['id']], $updateData);
                }
            }
            DB::commit();
        } catch (\Exception $e) {
            Log::info('Error:' . $e->getMessage() . ' at ' . $e->getFile() . ' line:' . $e->getLine() . '\n' . $e->getTraceAsString());
            DB::rollback();
        }
    }

    public function update(array $where, array $data)
    {
        return DB::table('warehouse_adjust')->where($where)->update($data);
    }
}